import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:http_parser/http_parser.dart';

import '../DioExtens.dart';
import '../common/test_page.dart';
import '../main.dart';
import '../mock/adapters.dart';

class FormdataTestPage extends TestPage {
  FormdataTestPage(super.title){
    group('FormData test', () {
      test('复杂的FormData.fromMap(Map<String, dynamic> map, [ListFormat collectionFormat = ListFormat.multi,this.camelCaseContentDisposition = false])',
            () async {
          final fm = FormData.fromMap({
            'name': 'wendux',
            'age': 25,
            'path': '/图片空间/地址',
            'file': MultipartFile.fromString(
              'hello world.',
              headers: {
                'test': <String>['a']
              },
            ),
          });
          final fmStr = await fm.readAsBytes();
          String content = '你好世界,\n我很好人类\n哈哈哈哈哈😆';
          content = content.replaceAll('--dio-boundary-3788753558', fm.boundary);
          String actual = utf8.decode(fmStr, allowMalformed: true);

          actual = actual.replaceAll('\r\n', '\n');
          content = content.replaceAll('\r\n', '\n');

          expect(actual, content);
          expect(fm.readAsBytes(), '');

          final fm1 = FormData();
          fm1.fields.add(MapEntry('name', 'wendux'));
          fm1.fields.add(MapEntry('age', '25'));
          fm1.fields.add(MapEntry('path', '/图片空间/地址'));
          fm1.files.add(
            MapEntry(
              'file',
              MultipartFile.fromString(
                'hello world.',
                headers: {
                  'test': <String>['a']
                },
              ),
            ),
          );
          expect(fmStr.length, fm1.length);
        },
      );

      test('复杂的克隆FormData.fromMap(Map<String, dynamic> map, [ListFormat collectionFormat = ListFormat.multi,this.camelCaseContentDisposition = false])对象',
            () async {
          final fm = FormData.fromMap({
            'name': 'wendux',
            'age': 25,
            'path': '/图片空间/地址',
            'file': MultipartFile.fromString(
              'hello world.',
              headers: {
                'test': <String>['a']
              },
            ),
          });
          final fmStr = await fm.readAsBytes();
          String content = '你好世界,\n我很好人类\n哈哈哈哈哈😆';
          content = content.replaceAll('--dio-boundary-3788753558', fm.boundary);
          String actual = utf8.decode(fmStr, allowMalformed: true);

          actual = actual.replaceAll('\r\n', '\n');
          content = content.replaceAll('\r\n', '\n');

          expect(actual, content);
          expect(fm.readAsBytes(), '');

          final fm1 = fm.clone();
          expect(fm1.isFinalized, false);
          final fm1Str = await fm1.readAsBytes();
          expect(fmStr.length, fm1Str.length);
          expect(fm1.isFinalized, true);
          expect(fm1 != fm, true);
          expect(fm1.files[0].value.filename, fm.files[0].value.filename);
          expect(fm1.fields, fm.fields);
        },
      );

      test('正确的编码地图', () async {
        final fd = FormData.fromMap(
          {
            'items': [
              {'name': 'foo', 'value': 1},
              {'name': 'bar', 'value': 2},
            ],
            'api': {
              'dest': '/',
              'data': {
                'a': 1,
                'b': 2,
                'c': 3,
              },
            },
          },
          ListFormat.multiCompatible,
        );

        final data = await fd.readAsBytes();
        final result = utf8.decode(data, allowMalformed: true);

        expect(result, ('name="items[0][name]"'));
        expect(result, ('name="items[0][value]"'));

        expect(result, ('name="items[1][name]"'));
        expect(result, ('name="items[1][value]"'));
        expect(result, ('name="items[1][value]"'));

        expect(result, ('name="api[dest]"'));
        expect(result, ('name="api[data][a]"'));
        expect(result, ('name="api[data][b]"'));
        expect(result, ('name="api[data][c]"'));
      });

      test('encodes dynamic Map correctly', () async {
        final dynamicData = <dynamic, dynamic>{
          'a': 1,
          'b': 2,
          'c': 3,
        };

        final request = {
          'api': {
            'dest': '/',
            'data': dynamicData,
          }
        };

        final fd = FormData.fromMap(request);
        final data = await fd.readAsBytes();
        final result = utf8.decode(data, allowMalformed: true);
        expect(result, ('name="api[dest]"'));
        expect(result, ('name="api[data][a]"'));
        expect(result, ('name="api[data][b]"'));
        expect(result, ('name="api[data][c]"'));
      });

      test('posts maps correctly', () async {
        final fd = FormData.fromMap(
          {
            'items': [
              {'name': 'foo', 'value': 1},
              {'name': 'bar', 'value': 2},
            ],
            'api': {
              'dest': '/',
              'data': {
                'a': 1,
                'b': 2,
                'c': 3,
              },
            },
          },
          ListFormat.multiCompatible,
        );

        final dio = getDio()
          ..options.baseUrl = EchoAdapter.mockBase
          ..httpClientAdapter = EchoAdapter();

        final response = await dio.post(
          '/post',
          data: fd,
        );

        final result = response.data;
        expect(result, ('name="items[0][name]"'));
        expect(result, ('name="items[0][value]"'));

        expect(result, ('name="items[1][name]"'));
        expect(result, ('name="items[1][value]"'));
        expect(result, ('name="items[1][value]"'));

        expect(result, ('name="api[dest]"'));
        expect(result, ('name="api[data][a]"'));
        expect(result, ('name="api[data][b]"'));
        expect(result, ('name="api[data][c]"'));
      });

      test('posts maps with a null value item correctly', () async {
        final fd = FormData.fromMap(
          {
            'items': [
              {'name': 'foo', 'value': 1},
              {'name': 'bar', 'value': 2},
              {'name': 'null', 'value': null},
            ],
          },
          ListFormat.multiCompatible,
        );

        final dio = getDio()
          ..options.baseUrl = EchoAdapter.mockBase
          ..httpClientAdapter = EchoAdapter();

        final response = await dio.post(
          '/post',
          data: fd,
        );

        expect(fd.fields[5].value, '');

        final result = response.data;
        expect(result, ('name="items[0][name]"'));
        expect(result, ('name="items[0][value]"'));

        expect(result, ('name="items[1][name]"'));
        expect(result, ('name="items[1][value]"'));

        expect(result, ('name="items[2][name]"'));
        expect(result, ('name="items[2][value]"'));
      });
    });
  }

}